﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FileTablePageViewModel.cs" company="Microsoft">
//   Microsoft
// </copyright>
// <summary>
//   Defines the FileTablePageViewModel type.
// </summary>
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// --------------------------------------------------------------------------------------------------------------------

namespace MySemanticSearch.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.ServiceModel.DomainServices.Client;
    using System.Windows.Controls;
    using System.Windows.Input;

    using MySemanticSearch.Commands;
    using MySemanticSearch.Model;
    using MySemanticSearch.Web.DataAccess;

    /// <summary>
    /// FileTable creation ViewModel
    /// </summary>
    public class FileTablePageViewModel : INotifyPropertyChanged
    {
        /// <summary>
        /// Status string
        /// </summary>
        private const string CreatingFileTable = "Please wait...";

        /// <summary>
        /// Status string
        /// </summary>
        private const string CreatingFileTableError = "Creation failed.";

        /// <summary>
        /// Dialog View
        /// </summary>
        private readonly ChildWindow dialogView;

        /// <summary>
        /// Domain Context
        /// </summary>
        private readonly SqlServerManagement sqlServerManagementContext = new SqlServerManagement();

        /// <summary>
        /// Selected database
        /// </summary>
        private Database selectedDatabase;

        /// <summary>
        /// FileTable name
        /// </summary>
        private string fileTableName;

        /// <summary>
        /// Database name
        /// </summary>
        private string databaseName;

        /// <summary>
        /// Create database checkbox
        /// </summary>
        private bool createDatabaseChecked;

        /// <summary>
        /// Enable database combobox
        /// </summary>
        private bool databaseSelectionEnabled;

        /// <summary>
        /// Selected Sql instance
        /// </summary>
        private string selectedSqlInstance;

        /// <summary>
        /// Indicates whether the View is enabled
        /// </summary>
        private bool isPageEnabled;

        /// <summary>
        /// Information message from an exception
        /// </summary>
        private string informationMessage;

        /// <summary>
        /// Initializes a new instance of the <see cref="FileTablePageViewModel"/> class.
        /// </summary>
        /// <param name="view">
        /// The dialog view.
        /// </param>
        public FileTablePageViewModel(ChildWindow view)
        {
            this.dialogView = view;
            this.InformationMessage = String.Empty;
            this.Databases = new ObservableCollection<Database>();
            this.IsCreateDatabaseChecked = false;
            this.IsPageEnabled = true;
        }

        /// <summary>
        /// Property changed handler
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Gets or sets a value indicating whether IsPageEnabled.
        /// </summary>
        public bool IsPageEnabled
        {
            get
            {
                return this.isPageEnabled;
            }

            set
            {
                this.isPageEnabled = value;
                this.NotifyPropertyChanged("IsPageEnabled");
            }
        }

        /// <summary>
        /// Gets or sets InformationMessage.
        /// </summary>
        public string InformationMessage
        {
            get
            {
                return this.informationMessage;
            }

            set
            {
                this.informationMessage = value;
                this.NotifyPropertyChanged("InformationMessage");
            }
        }

        /// <summary>
        /// Gets or sets SelectedSqlInstance.
        /// </summary>
        public string SelectedSqlInstance
        {
            get
            {
                return this.selectedSqlInstance;
            }

            set
            {
                this.selectedSqlInstance = value;
                if (null == value)
                {
                    return;
                }

                this.NotifyPropertyChanged("SelectedSqlInstance");
                this.sqlServerManagementContext.GetDatabaseNameList(this.SelectedSqlInstance, false, this.OnGetDatabasesCompleted, null);
            }
        }

        /// <summary>
        /// Gets or sets SelectedDatabase.
        /// </summary>
        public Database SelectedDatabase
        {
            get
            {
                return this.selectedDatabase;
            }

            set
            {
                this.selectedDatabase = value;
                if (this.databaseSelectionEnabled)
                {
                    this.DatabaseName = this.selectedDatabase == null ? string.Empty : this.selectedDatabase.Name;
                }

                this.NotifyPropertyChanged("SelectedDatabase");
            }
        }

        /// <summary>
        /// Gets or sets FileTableName.
        /// </summary>
        public string FileTableName
        {
            get
            {
                return this.fileTableName;
            }

            set
            {
                this.fileTableName = value;
                this.NotifyPropertyChanged("FileTableName");
            }
        }

        /// <summary>
        /// Gets or sets DatabaseName.
        /// </summary>
        public string DatabaseName
        {
            get
            {
                return this.databaseName;
            }

            set
            {
                this.databaseName = value;
                this.NotifyPropertyChanged("DatabaseName");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether IsCreateDatabaseChecked.
        /// </summary>
        public bool IsCreateDatabaseChecked
        {
            get
            {
                return this.createDatabaseChecked;
            }

            set
            {
                this.createDatabaseChecked = value;
                this.IsDatabaseSelectionEnabled = !value;
                this.NotifyPropertyChanged("IsDatabaseTextEnabled");
                this.NotifyPropertyChanged("IsCreateDatabaseChecked");

                if (this.createDatabaseChecked)
                {
                    this.DatabaseName = string.Empty;
                    this.SelectedDatabase = null;
                }
                else if (this.SelectedSqlInstance != null)
                {
                    this.sqlServerManagementContext.GetDatabaseNameList(this.SelectedSqlInstance, false, this.OnGetDatabasesCompleted, null);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether IsDatabaseSelectionEnabled.
        /// </summary>
        public bool IsDatabaseSelectionEnabled
        {
            get
            {
                return this.databaseSelectionEnabled;
            }

            private set
            {
                this.databaseSelectionEnabled = value;
                this.NotifyPropertyChanged("IsDatabaseSelectionEnabled");
            }
        }

        /// <summary>
        /// Gets a value indicating whether IsDatabaseTextEnabled.
        /// </summary>
        public bool IsDatabaseTextEnabled
        {
            get
            {
                return !this.databaseSelectionEnabled;
            }
        }

        /// <summary>
        /// Gets CreateFileTableCommand.
        /// </summary>
        public ICommand CreateFileTableCommand
        {
            get
            {
                return new RelayCommand(this.CreateFileTable);
            }
        }

        /// <summary>
        /// Gets Databases.
        /// </summary>
        public ObservableCollection<Database> Databases
        {
            get;
            private set;
        }

        /// <summary>
        /// Create File Table method
        /// </summary>
        public void CreateFileTable()
        {
            if (this.SelectedSqlInstance == null || this.DatabaseName == null || this.FileTableName == null)
            {
                return;
            }

            this.InformationMessage = CreatingFileTable;
            this.IsPageEnabled = false;
            this.sqlServerManagementContext.CreateFileTable(this.SelectedSqlInstance, this.DatabaseName, this.FileTableName, this.IsCreateDatabaseChecked, this.OnCreateFileTableCompleted, null);
        }

        /// <summary>
        /// Shows the Information Dialog error
        /// </summary>
        /// <param name="args">
        /// The arguments.
        /// </param>
        private static void ShowError(OperationBase args)
        {
            args.MarkErrorAsHandled();
            var errorDialog = new ErrorDialogPage(args.Error.Message);
            errorDialog.Show();
        }

        /// <summary>
        /// Uses the RIA service to retrieve all databases
        /// </summary>
        /// <param name="args">
        /// The args param.
        /// </param>
        private void OnGetDatabasesCompleted(InvokeOperation args)
        {
            if (args.HasError)
            {
                ShowError(args);
                return;
            }

            var dbs = (string[])args.Value;

            this.Databases.Clear();

            foreach (var database in dbs.Select(db => new Database { Name = db }))
            {
                this.Databases.Add(database);
            }

            if (this.Databases.Count() > 0)
            {
                this.SelectedDatabase = this.Databases.First();
            }
            else
            {
                this.IsCreateDatabaseChecked = true;
            }
        }

        /// <summary>
        /// Callback method for creating a FileTable
        /// </summary>
        /// <param name="args">
        /// The args param.
        /// </param>
        private void OnCreateFileTableCompleted(InvokeOperation args)
        {
            if (args.HasError)
            {
                this.InformationMessage = CreatingFileTableError;
                this.IsPageEnabled = true;
                ShowError(args);
                return;
            }
            
            this.dialogView.DialogResult = true;
        }

        #region Notify Property Changed
        /// <summary>
        /// Notify property Changed
        /// </summary>
        /// <param name="info">
        /// The info string.
        /// </param>
        private void NotifyPropertyChanged(string info)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}
